
#include "baby_crying_window.h"
#include "ui_baby_crying_window.h"

baby_crying_window::baby_crying_window(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::baby_crying_window)
    , statistic(new QLabel(this))
{
    ui->setupUi(this);
    update_time();
    ui->wave->chart()->setTheme(QChart::ChartThemeQt);
    timer_to_show_time.start(1e3);
    connect(std::addressof(timer_to_show_time), QTimer::timeout, this, update_time);
    connect(std::addressof(timer_for_playing_process), QTimer::timeout, this, [this]
            {
                ui->play_process_slider->blockSignals(true);
                ui->play_process_slider->setValue(ui->play_process_slider->value() + slider_scale);
                ui->play_process_slider->blockSignals(false);
                double total_seconds = s.seconds();
                double time = 1 + ui->play_process_label->text()
                                      .mid(0, ui->play_process_label->text().indexOf('/')).toDouble();
                if (time < total_seconds)
                    ui->play_process_label->setText(QString::number(time, 'f', 4)
                        + '/' + QString::number(total_seconds) + 's');
                else
                {
                    ui->play_process_label->setText(QString::number(total_seconds, 'f', 4)
                        + '/' + QString::number(total_seconds) + 's');
                    state = play_state::none;
                    ui->play->setStyleSheet("border-image: url(:/play.jpg);");
                    timer_for_playing_process.stop();
                }
            });
    setWindowTitle("音频播放器");
    statistic->setGeometry(ui->wave->geometry());
    statistic->hide();
}

baby_crying_window::~baby_crying_window()
{
    delete ui;
    p.reset();
    p.unprepare();
    p.closeOutAudioBlock();
    timer_to_show_time.stop();
}

void baby_crying_window::on_awake_clicked()
{
    openfile();
}

void baby_crying_window::openfile()
{
    fileName = QFileDialog::getOpenFileName(this,tr("文件对话框"),"D:",tr("音频文件(*wav)"));
    //qDebug()<<"fileName:"<<fileName;
    try {
        s.load_file(fileName.toLocal8Bit().toStdString());
    }
    catch (const file_not_found_exception&) {
        return;
    }
    catch (const parse_exception&) {
        return;
    }

    timer_for_playing_process.stop();
    state = play_state::none;
    p.reset();
    p.unprepare();
    p.set_sound(s);
    ui->play_process_slider->blockSignals(true);
    ui->play_process_slider->setValue(0);
    ui->play_process_slider->blockSignals(false);

    ui->play->setStyleSheet("border-image: url(:/play.jpg);");
    ui->play->setEnabled(true);
    ui->wave->chart()->removeAllSeries();
    QLineSeries *wave_series = new QLineSeries;
    wave_series->setMarkerSize(1);
    wave_series->setUseOpenGL(true);
//    ui->wave->setChart(new QChart());
//    wave_series.clear();
//    auto spec = s.power_spectrum_real_part();
//    qDebug() << spec(0);
//    for (double f = 0; f < 8e3; ++f)
//    {
//        series->append(f, spec(f * M_PI * 2));
//    }
    double total_seconds = s.seconds();
    for (int i = 0; i < s.data_count; ++i)
        wave_series->append(total_seconds * i/s.data_count, s.normalized(i));
    ui->wave->chart()->addSeries(wave_series);
    ui->wave->chart()->createDefaultAxes();
    ui->wave->chart()->legend()->setVisible(false);
//    ui->play_process_slider->setMinimum(0);
    ui->play_process_slider->setMaximum(s.seconds() * slider_scale);
    ui->play_process_slider->setPageStep(slider_scale);
//    ui->play_process_label->setText("0.0/" + QString::number(s.seconds()));
//    on_play_process_slider_valueChanged(ui->play_process_slider->value());
    ui->wave_radio->click();
    statistic->setText(QString::fromStdString(s.statistic_description()));
}

void baby_crying_window::on_diaper_clicked()
{
    openfile();
}


void baby_crying_window::on_hug_clicked()
{
    openfile();
}


void baby_crying_window::on_hungry_clicked()
{
    openfile();
}


void baby_crying_window::on_sleepy_clicked()
{
    openfile();
}


void baby_crying_window::on_uncomfortable_clicked()
{
    openfile();
}


void baby_crying_window::on_handbook_clicked()
{
    (new HandbookDialog(this))->show();
}


void baby_crying_window::on_play_clicked()
{
    switch (state)
    {
    case play_state::none:
        ui->play_process_slider->blockSignals(true);
        ui->play_process_slider->setValue(0);
        ui->play_process_slider->blockSignals(false);
        on_play_process_slider_valueChanged(0);
//        play(ui->play_process_slider->value());
        ui->play->setStyleSheet("border-image: url(:/pause.jpg);");
        state = play_state::playing;
        timer_for_playing_process.start(1e3);
        break;
    case play_state::playing:
        p.pause();
        ui->play->setStyleSheet("border-image: url(:/play.jpg);");
        state = play_state::pause;
        timer_for_playing_process.stop();
        break;
    case play_state::pause:
        p.restart();
        ui->play->setStyleSheet("border-image: url(:/pause.jpg);");
        state = play_state::playing;
        timer_for_playing_process.start(1e3);
        break;
    }
}

void baby_crying_window::on_play_process_slider_valueChanged(int value)
{
    if (state == play_state::no_sound)
        return;
    if (state not_eq play_state::playing)
        state = play_state::pause;
    play(value);
    ui->play_process_label->setText(QString::number(value / slider_scale, 'f', 4)
                                    + '/' + QString::number(s.seconds(), 'f', 4) + 's');
}

void baby_crying_window::play(int value)
{
    double precent = static_cast<double>(value - ui->play_process_slider->minimum())
                     / (ui->play_process_slider->maximum() - ui->play_process_slider->minimum());
    int passed_bytes = (static_cast<int>(s.data_bytes * precent) >> 1) << 1;
    char *data = s.data._c + passed_bytes;
    p.reset();
    p.unprepare();
    try
    {
        new std::thread([this, data, passed_bytes]()
                        {
                            while (state not_eq play_state::playing)
                                Sleep(500);
                            p.writeOutAudioBlock(data, s.data_bytes - passed_bytes);
                            p.unprepare();
                        });
    }
    catch (const play_exception& e)
    {
        qDebug() << e.what();
    }
}

void baby_crying_window::update_time()
{
    ui->current_time->setText(QDateTime::currentDateTime().toString("hh:mm:ss"));
}


void baby_crying_window::on_statistic_radio_clicked()
{
    if (state == play_state::no_sound)
        return;
    ui->wave->hide();
    statistic->show();
}

void baby_crying_window::on_wave_radio_clicked()
{
    if (state == play_state::no_sound)
        return;
    statistic->hide();
    ui->wave->show();
}
